package versi.vitro.oaiserviceprovider.service.validation.helper;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Document;

import versi.vitro.oaiserviceprovider.service.validation.api.ValidationHelper;
import versi.vitro.oaiserviceprovider.xml.XmlDomBuilder;
import versi.vitro.oaiserviceprovider.xml.XmlDomBuilderFactory;
import versi.vitro.oaiserviceprovider.xml.XmlSchema;
import versi.vitro.oaiserviceprovider.xml.XmlSchemaFactory;
import versi.vitro.oaiserviceprovider.xml.XmlValidator;

public class ValidationHelperImplTest {

    private Mockery context;

    @BeforeMethod
    public void setUp() {
	context = new Mockery();
    }

    @Test
    public void testAddFiletoSchemas() {

	final File schemaFile = new File("a file path");

	final Source source = context.mock(Source.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(source).setSystemId(schemaFile.getAbsolutePath());
	    }
	});

	List<Source> sources = new ArrayList<Source>();

	ValidationHelper validationHelper = new ValidationHelperImpl() {
	    protected Source createSchemaSource(File schemaFile) {
		return source;
	    }
	};

	validationHelper.addFiletoSchemas(schemaFile, sources);

	context.assertIsSatisfied();
    }

    @Test
    public void testValidateAgainstSchema() {

	final String sourceXsdStr = "<style></style>";	
	final InputStream xsdInputStream = new ByteArrayInputStream(sourceXsdStr.getBytes());	
	final Source[] sourceXsd = {new StreamSource(xsdInputStream)};
	
	final String sourceXmlStr = "<root></root>";
	final byte[] sourceXmlBytes =  sourceXmlStr.getBytes();
	final InputStream xmlInputStream = new ByteArrayInputStream(sourceXmlBytes);
	
	final Document dummyDocument = context.mock(Document.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final Source xmlInput = context.mock(Source.class, "xmlInput");
	context.checking(new Expectations() {
	    {
	    }
	});

	final Result result = context.mock(Result.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final XmlDomBuilder xmlDomBuilder = context.mock(XmlDomBuilder.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(xmlDomBuilder).parse(xmlInputStream); will(returnValue(dummyDocument));
	    }
	});

	final XmlDomBuilderFactory xmlDomBuilderFactory = context.mock(XmlDomBuilderFactory.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(xmlDomBuilderFactory).create(); will(returnValue(xmlDomBuilder));
	    }
	});


	final XmlValidator validator = context.mock(XmlValidator.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(validator).validate(xmlInput, result); will(returnValue(true));
	    }
	});

	final XmlSchema xmlSchema = context.mock(XmlSchema.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(xmlSchema).createValidator(); will(returnValue(validator));
	    }
	});

	final XmlSchemaFactory xmlSchemFactory = context.mock(XmlSchemaFactory.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(xmlSchemFactory).create(sourceXsd); will(returnValue(xmlSchema));
	    }
	});

	ValidationHelper validationHelper = new ValidationHelperImpl(null, xmlDomBuilderFactory, xmlSchemFactory)
	{
	    protected Result createResult() {
		return result;
	    }

	    protected Source createSource(Document dom) {
		return xmlInput;
	    }

	    protected InputStream createXmlDocumentInputStream(byte[] source) {
		assert sourceXmlStr.equals(new String(source));
		return xmlInputStream;
	    }
	};
	
	boolean isValid = validationHelper.validateAgainstSchema(sourceXmlBytes, sourceXsd);

	assert isValid;
	context.assertIsSatisfied();
    }
}
